package com.freek.ScreenDrop;
import java.awt.AWTException;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.dropbox.client2.DropboxAPI;
import com.dropbox.client2.DropboxAPI.DropboxLink;
import com.dropbox.client2.DropboxAPI.Entry;
import com.dropbox.client2.exception.DropboxException;
import com.dropbox.client2.session.WebAuthSession;

public class Capture
{
	static Robot robot;
	public static final String PREFIX = "Screenshot ";
	static ExecutorService uploads;
	static
	{
		try
		{
			robot = new Robot();
		} catch (AWTException e)
		{
			e.printStackTrace();
		}
		
		uploads = Executors.newSingleThreadExecutor();
	}

	/**
	 * Save a screenshot of the desktop to a .png at the given path
	 * 
	 * @param filename
	 *            The path to store the captured .png
	 * @throws IOException
	 * @throws AWTException
	 * @throws URISyntaxException 
	 * @throws DropboxException 
	 */
	public static void desktop() throws IOException,
			AWTException, DropboxException, URISyntaxException
	{
		BufferedImage img = ScreenImage.createDesktopImage();
		queueUpload(img);
	}

	public static void window() throws IOException
	{
		robot.keyPress(KeyEvent.VK_ALT);
		robot.keyPress(KeyEvent.VK_PRINTSCREEN);
		robot.keyRelease(KeyEvent.VK_PRINTSCREEN);
		robot.keyRelease(KeyEvent.VK_ALT);

		try
		{
			// TODO: find a better way than sleeping to wait for the clipboard
			Thread.sleep(100);
		} catch (InterruptedException e)
		{
			e.printStackTrace();
		}
		Image capture = getClipboardImage();
		queueUpload(((BufferedImage) capture));
	}

	/**
	 * Save a screenshot of a region of the desktop to a .png at the given path
	 * 
	 * @param filename
	 *            The path to store the captured .png
	 * @param bounds
	 *            The region of the desktop to capture
	 * @throws IOException
	 * @throws AWTException
	 */
	public static void region(Rectangle bounds)
			throws IOException, AWTException
	{
		queueUpload(ScreenImage.createImage(bounds));
	}

	public static void file(File file)
	{
		//TODO: copy file
	}

	public static void clipboard()
	{
		//TODO: copy clipboard text or files
	}

	/**
	 * Get an image stored in the clipboard.
	 * 
	 * @author Shaunak from
	 *         http://stackoverflow.com/questions/2475303/java-library
	 *         -for-capturing-active-window-screenshot
	 * @return Image stored in clipboard, null if there is no image
	 */
	private static Image getClipboardImage()
	{
		Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard()
				.getContents(null);

		try
		{
			if (t != null && t.isDataFlavorSupported(DataFlavor.imageFlavor))
			{
				Image text = (Image) t.getTransferData(DataFlavor.imageFlavor);
				return text;
			}
		} catch (UnsupportedFlavorException | IOException e)
		{
			e.printStackTrace();
		}
		return null;
	}

	private static Object getClipboard()
	{
		Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
		try
		{
			if(t != null && t.isDataFlavorSupported(DataFlavor.plainTextFlavor))
			{
				return t.getTransferData(DataFlavor.plainTextFlavor);
			}
//			else if(t != null && t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
//			{
//				return t.getTransferData(DataFlavor.javaFileListFlavor);
//			}
		} catch (UnsupportedFlavorException | IOException e)
		{
			e.printStackTrace();
		}
		return null;
	}

	// private static BufferedImage toBufferedImage(Image image)
	// {
	// BufferedImage bufImage =
	// GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration()
	// .createCompatibleImage(image.getWidth(null), image.getHeight(null),
	// Transparency.OPAQUE);
	//
	// Graphics g = bufImage.getGraphics();
	// g.drawImage(image, 0, 0, null);
	// g.dispose();
	//
	// return bufImage;
	// }
	
	private final static SimpleDateFormat sdl = new SimpleDateFormat("yyyy-MM-dd HH.mm.ss.SSSS");

	private static String generateFilename(String prefix)
	{
		return prefix + sdl.format(new Date()) + ".png";
	}
	
	private static void queueUpload(final BufferedImage image)
	{
		Runnable upload = new Runnable()
		{
			@Override
			public void run()
			{
				DropboxAPI<WebAuthSession> dropbox = Authenticator.dropboxAPI;
				if(!dropbox.getSession().isLinked())
				{
					try
					{
						dropbox = Authenticator.authenticate();
					} catch (DropboxException
							| IOException | URISyntaxException e)
					{
						e.printStackTrace();
					}
				}
				String tempPath = "temp"+System.currentTimeMillis()+".png";
				try
				{
					ScreenImage.writeImage(image, tempPath);
				} catch (IOException e1)
				{
					e1.printStackTrace();
				}
				File f = new File(tempPath);
				try(InputStream in = new FileInputStream(f))
				{
					Entry entry = dropbox.putFile(generateFilename(PREFIX), in,
							f.length(), null, null);
					DropboxLink link = dropbox.share(entry.path);
					copyToClipboard(link.url);
					Main.trayIcon.displayMessage("Uploaded Screenshot!", "The screenshot has been uploaded to "+link.url, TrayIcon.MessageType.INFO);
				} 
				catch (DropboxException | IOException e)
				{
					e.printStackTrace();
				}
				f.delete();
				
			}
		};
		uploads.submit(upload);
	}
	
	private static void copyToClipboard(String copy)
	{
		Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(copy), null);
	}
}
